﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Controls.Primitives;
using SharpMap.Presentation.Views;
using SharpMap.Rendering.Rendering2D;
using SharpMap.Presentation.Wpf;
using SharpMap.Presentation.Wpf.Converters;
namespace SharpMap.Wpf
{
 
    /// <summary>
    /// The main control used to show maps
    /// This is the facade to most of the common uses of SharpMap WPF Controls.
    /// In Particular it provide the following functionality:
    /// <list type="number">
    ///     <item>Prensentation and instansiation of the 
    ///            underlying <see cref="SharpMap.Map">SharpMap.Map</see>   
    ///     </item>
    ///     <item>Content model</item>
    ///     <item> Toolbar </item>
    /// </list>
    /// 
    /// </summary>
    [TemplatePart(Name="PART_EmbededToolBar",Type=typeof(FrameworkElement))]
    [TemplatePart(Name = "PART_InfoPanel", Type = typeof(FrameworkElement))]
    [TemplatePart(Name = "PART_MapView", Type = typeof(Panel))]
    public class MapControl : ItemsControl
    {
        //-----------------------------------------------------
        //
        //  Dependency Properties
        //
        //-----------------------------------------------------

        #region Dependency Properties



        public static MatrixTransform GetToViewTransform(DependencyObject obj)
        {
            return (MatrixTransform)obj.GetValue(ToViewTransformProperty);
        }

        public static void SetToViewTransform(DependencyObject obj, MatrixTransform value)
        {
            obj.SetValue(ToViewTransformProperty, value);
        }

        public static readonly DependencyProperty ToViewTransformProperty =
            DependencyProperty.RegisterAttached("ToViewTransform", typeof(MatrixTransform), typeof(MapControl),
            new FrameworkPropertyMetadata(default(MatrixTransform),
                 FrameworkPropertyMetadataOptions.Inherits | FrameworkPropertyMetadataOptions.OverridesInheritanceBehavior));


        public MatrixTransform ToViewTransform
        {
            get
            {
                return MapControl.GetToViewTransform(this);
            }
            set
            {
                MapControl.SetToViewTransform(this, value);
            }
        }




        public IWpfTheme Theme
        {
            get { return (IWpfTheme)GetValue(ThemeProperty); }
            set { SetValue(ThemeProperty, value); }
        }
        public static readonly DependencyProperty ThemeProperty =
            DependencyProperty.Register("Theme", typeof(IWpfTheme), typeof(MapControl), new UIPropertyMetadata(default(IWpfTheme)));



        
        
        #region Map
        public SharpMap.Map Map
        {
            get { return GetMap(this); }
            set { SetValue(MapProperty, value); }
        }

        internal static SharpMap.Map GetMap(DependencyObject obj)
        {
            return (SharpMap.Map)obj.GetValue(MapProperty);
        }
        public static readonly DependencyProperty MapProperty =
            DependencyProperty.Register("Map", typeof(SharpMap.Map), typeof(MapControl)
            , new FrameworkPropertyMetadata(
                default(SharpMap.Map),
                MapPropertyChanged));


        static void MapPropertyChanged(DependencyObject target, DependencyPropertyChangedEventArgs e)
        {
            MapControl This = target as MapControl;
            if (This != null)
            {
                //This.DataContext = This._viewModel;
            }
        }

        private void ResetAll()
        {
            
        }



        #endregion

        
        
        
        
        
        #region Layers

        #endregion


        /// <summary>
        /// Gets or sets a value indicating that the EmbededToolbar is visible
        /// This is a dependency property. 
        /// </summary>
        public bool IsEmbededToolbarVisible
        {
            get { return (bool)GetValue(IsEmbededToolbarVisibleProperty); }
            set { SetValue(IsEmbededToolbarVisibleProperty, value); }
        }
        public static readonly DependencyProperty IsEmbededToolbarVisibleProperty =
            DependencyProperty.Register("IsEmbededToolbarVisible", typeof(bool), typeof(MapControl), new UIPropertyMetadata(default(bool)));

        /// <summary>
        /// Gets or sets a value indicating that the InfoPanel is visible
        /// This is a dependency property. 
        /// </summary>
        public bool IsInfoPanelVisible
        {
            get { return (bool)GetValue(IsInfoPanelVisibleProperty); }
            set { SetValue(IsInfoPanelVisibleProperty, value); }
        }
        public static readonly DependencyProperty IsInfoPanelVisibleProperty =
            DependencyProperty.Register("IsInfoPanelVisible", typeof(bool), typeof(MapControl), new UIPropertyMetadata(default(bool)));

        #endregion

        //-----------------------------------------------------
        //
        //  Construction
        //
        //-----------------------------------------------------

        static MapControl()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(MapControl), new FrameworkPropertyMetadata(typeof(MapControl)));
            
        }

        public MapControl()
        {
            //_viewModel = new MapControlViewModel(new Map());
            Map = new Map();
            AddHandler(CommandManager.CanExecuteEvent,new CanExecuteRoutedEventHandler (OnCanExecuteCommand));
            AddHandler(CommandManager.ExecutedEvent, new ExecutedRoutedEventHandler(OnExecutedCommand));
        }

        //-----------------------------------------------------
        //
        //  Control/FrameworkElement overrides
        //
        //-----------------------------------------------------

        #region Control/FrameworkElement overrides
        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            _defaultView = Template.FindName("PART_DefaultMapView", this) as MapView;
            if (_defaultView != null)
            {
                _defaultView.Theme = Theme;
                _defaultView.Map = Map;
               // WpfViewTransform="{Binding Path=ToViewTransform,  RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:MapControl}} }"
                Binding b = new Binding("ToViewTransform");
                b.Converter = MatrixToTransformConverter.Instance;
                b.Source = _defaultView;
                b.Mode = BindingMode.OneWay;
                SetBinding(ToViewTransformProperty,b);
                
            }
            _embededToolBar = Template.FindName("PART_EmbededToolBar", this) as FrameworkElement;
            _infoPanel = Template.FindName("PART_InfoPanel", this) as FrameworkElement;
            object o = FindName("PART_MapViewPanel");
        }

        //-----------------------------------------------------
        //
        //  ItemsControl overrides
        //
        //-----------------------------------------------------

        #region ItemsControl

        protected override void OnItemsChanged(System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            base.OnItemsChanged(e);
        }

        protected override void OnItemsSourceChanged(System.Collections.IEnumerable oldValue, System.Collections.IEnumerable newValue)
        {
            base.OnItemsSourceChanged(oldValue, newValue);
        }
        protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
        {
            MapLayer layer;
            if ((layer = element as MapLayer) != null)
            {
                layer.PrapareMapLayer(item);
                if (layer.Layer != null)
                {
                    if (_defaultView != null)
                    {
                        Map.Layers.Insert(0, layer.Layer);
                        //Map.AddLayer();
                        _defaultView.ZoomToExtents();
                    }
                }
            }
            else
            {
                base.PrepareContainerForItemOverride(element, item);
            }
        }

        private void OnCanExecuteCommand(object sender, CanExecuteRoutedEventArgs args)
        {
            //TODO: here should be all the sophisticated handeling, but if all failes - fall back to the view...
            RoutedCommand routedCommand = args.Command as RoutedCommand;
            if (_defaultView != null)
            {
                args.CanExecute = routedCommand.CanExecute(args.Parameter, _defaultView);
            }
        }

        private void OnExecutedCommand(object sender, ExecutedRoutedEventArgs args)
        {
            RoutedCommand routedCommand = args.Command as RoutedCommand;
            if (_defaultView != null)
            {
                routedCommand.Execute(args.Parameter, _defaultView);
                args.Handled = true;
            }

        }
        //protected override void ClearContainerForItemOverride(DependencyObject element, object item)
        //{
        //    base.ClearContainerForItemOverride(element, item);
        //}

        //protected override DependencyObject GetContainerForItemOverride()
        //{
        //    return new MapLayer();
        //}

        //protected override bool IsItemItsOwnContainerOverride(object item)
        //{
        //    return item is MapLayer;
        //} 
        #endregion //ItemsControl overrides
         
        #endregion //FrameworkElement overrides

        MapView _defaultView;
        
        FrameworkElement _embededToolBar;
        FrameworkElement _infoPanel;
        NullElement _hitTestLayer;
        
        MapControlViewModel _viewModel;


    }

    internal class NullElement : UIElement
    {
        // Methods
        protected override GeometryHitTestResult HitTestCore(GeometryHitTestParameters hitTestParams)
        {
            return new GeometryHitTestResult(this, IntersectionDetail.FullyContains);
        }

        protected override HitTestResult HitTestCore(PointHitTestParameters hitTestParams)
        {
            return new PointHitTestResult(this, hitTestParams.HitPoint);
        }
    }

}
